package com.anuo.app.modules.user.controller;

import com.anuo.app.common.entity.ErrorCode;
import com.anuo.app.common.entity.LocationFilter;
import com.anuo.app.common.entity.Request;
import com.anuo.app.common.globalhandle.AppException;
import com.anuo.app.common.globalhandle.BaseController;
import com.anuo.app.common.persistence.PageData;
import com.anuo.app.common.security.SecurityUtil;
import com.anuo.app.common.utils.Assert;
import com.anuo.app.common.utils.JsonUtil;
import com.anuo.app.modules.user.entity.*;
import com.anuo.app.modules.user.service.UserService;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.ReuseExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@RestController
public class UserController extends BaseController {
    @Autowired
    UserService userService;

    /**
     * 注册用户
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiRegisterUser", produces = {"application/json;charset=UTF-8"})
    public String apiRegisterUser(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = JsonUtil.fromJson(encryptedReq,
                new TypeReference<Request<UserAccount>>() {
                }).getFirstEntity();
        //数据验证
        if (userService.isExistUserByMobile(userAccount)) {
            return rspError("你的手机号已经注册过,请直接登录");
        }

        if (StringUtils.isEmpty(userAccount.getCityid())) {
            return rspError("城市Id不能为空");
        }
        if (StringUtils.isEmpty(userAccount.getPet_name())) {
            return rspError("昵称不能为空");
        }
        if (StringUtils.isEmpty(userAccount.getMobile())) {
            //特别注意, 一定要让用户手机号注册, 不然后面整个系统流转要用验证码, 到时候再去绑定手机号就迟了,需要填各种坑!
            return rspError("电话号码不能为空");
        }

        userService.registerUser(userAccount);
        return rspSuccess(userAccount);
    }

    /**
     * 用户登录
     *
     * @param encryptedReq
     * @return
     * @throws IOException
     */
    @PostMapping(value = "v1/apiLogin", produces = {"application/json;charset=UTF-8"})
    public String apiLogin(@RequestBody String encryptedReq) throws IOException {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getDevice_version(), "没有附加版本号");
        if (userService.isHaveNewVerison(userAccount.getDevice_version(), userAccount.getDevice_type())) {
            return rspError(ErrorCode.NEW_VERSION, "发现新版本, 请更新");
        }

        //登陆验证
        String token = userService.validUser(userAccount.getPassword_param(), userAccount.getMobile()
                , userAccount.isPasswordDirectCompare());
        if (StringUtils.isNotEmpty(token)) {
            return rspSuccess(token);//拿到token表示验证成功
        } else {
            return rspError("登陆失败, 用户名或密码错误");
        }

    }

    /**
     * 微信登录
     *
     * @param encryptedReq
     * @return
     * @throws IOException
     */
    @PostMapping(value = "v1/apiWeiXinLogin", produces = {"application/json;charset=UTF-8"})
    public String apiWeiXinLogin(@RequestBody String encryptedReq) throws IOException {
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getWeixin_tempcode(), "微信登陆临时编码不能为空");
        //先获取此用户的微信UnionId
        WeiXinUserInfo weiXinUserInfo = userService.getWeiXinUserInfo(userAccount.getWeixin_tempcode());
        Assert.isEmpty(weiXinUserInfo.getUnionid(), "微信的UnionId获取失败");
        userAccount.setWeixin_unionid(weiXinUserInfo.getUnionid());
        //通过unionId查询此用户
        UserFilter userFilter = new UserFilter();
        userFilter.setWeixin_unionid(weiXinUserInfo.getUnionid());
        UserAccount userAccount_db = userService.getUser(userFilter);
        //不存在unionId记录, 自动创建一个账号
        if (userAccount_db == null) {
            userAccount_db = new UserAccount();
            userAccount_db.setPet_name(weiXinUserInfo.getNickname());
            userAccount_db.setSex(Integer.toString(weiXinUserInfo.getSex()));
            userAccount_db.setWeixin_unionid(weiXinUserInfo.getUnionid());
            if (weiXinUserInfo.getHeadimgurl().equals("/0")) { //0表示没有头像, 腾讯坑爹
                userAccount_db.setHeadurl(weiXinUserInfo.getHeadimgurl());
            }
            int random = ThreadLocalRandom.current().nextInt(100000000, 999999999);
            //加上default 单词, 表明这个密码是自动生成的
            String hashPassword = "default_" + SecurityUtil.hashPassword(Integer.toString(random));
            userAccount_db.setUser_password(hashPassword);
            userService.addUser(userAccount_db);
            //指引前端跳到绑定手机界面(因为自动创建的账户缺失手机号)
            userAccount_db.setNext_step("GoBindMobile");
        } else {
            //存在unionid 记录, 直接返回账户和密码供APP端自动登陆
            userAccount_db.setPassword_param(userAccount_db.getUser_password());
            //指引前端直接去登陆
            userAccount_db.setNext_step("GoLogin");
        }
        return rspSuccess(userAccount_db);

    }

    /**
     * qq登录
     *
     * @param encryptedReq
     * @return
     * @throws IOException
     */
    @PostMapping(value = "v1/apiQQLogin", produces = {"application/json;charset=UTF-8"})
    public String apiQQLogin(@RequestBody String encryptedReq) throws IOException {
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getQq_openid(), "qq openid 不能为空");
        //通过openid查询此用户
        UserFilter userFilter = new UserFilter();
        userFilter.setQq_openid(userAccount.getQq_openid());
        UserAccount userAccount_db = userService.getUser(userFilter);
        //不存在openid记录, 自动创建一个账号
        if (userAccount_db == null) {

            int random = ThreadLocalRandom.current().nextInt(100000000, 999999999);
            //加上default 单词, 表明这个密码是自动生成的
            String hashPassword = "default_" + SecurityUtil.hashPassword(Integer.toString(random));
            userAccount.setUser_password(hashPassword);
            userService.addUser(userAccount);
            //指引前端跳到绑定手机界面(因为自动创建的账户缺失手机号)
            userAccount.setNext_step("GoBindMobile");
        } else {
            //存在openid 记录, 直接返回账户和密码供APP端自动登陆
            userAccount.setPassword_param(userAccount_db.getUser_password());
            //指引前端直接去登陆
            userAccount.setNext_step("GoLogin");
        }
        return rspSuccess(userAccount);

    }

    /**
     * 用户退出
     *
     * @param encryptedReq
     * @return
     * @throws IOException
     */
    @PostMapping(value = "v1/apiLogout", produces = {"application/json;charset=UTF-8"})
    public String apiLogout(@RequestBody String encryptedReq) throws IOException {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        userService.logout(userAccount);
        return rspSuccess();
    }

    /**
     * 修改用户信息
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiUpdateUser", produces = {"application/json;charset=UTF-8"})
    public String apiUpdateUser(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        Assert.isEmpty(userAccount.getCityid(), "城市id不能为空");
        Assert.isEmpty(userAccount.getPet_name(), "昵称不能为空");
        userService.updateUserAccount(userAccount);
        return rspSuccess();
    }

    /**
     * 获取用户信息
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiGetUser", produces = {"application/json;charset=UTF-8"})
    public String apiGetUser(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserFilter userFilter = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserFilter>>() {
        }).getFirstEntity();
        return rspSuccess(userService.getUser(userFilter));
    }

    /**
     * 修改手机号
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiUpdateMobile", produces = {"application/json;charset=UTF-8"})
    public String apiUpdateMobile(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        Assert.isEmpty(userAccount.getMobile(), "手机号不能为空");
        Assert.isEmpty(userAccount.getMobile_code(), "验证码不能为空");
        userService.updateMobile(userAccount);
        return rspSuccess();
    }

    /**
     * 修改密码
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiUpdatePassword", produces = {"application/json;charset=UTF-8"})
    public String apiUpdatePassword(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        Assert.isEmpty(userAccount.getOld_password(), "原密码不能为空");
        Assert.isEmpty(userAccount.getNew_password(), "新密码不能为空");
        userService.updatePassword(userAccount);
        return rspSuccess();
    }

    /**
     * 充值密码
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiResetPassword", produces = {"application/json;charset=UTF-8"})
    public String apiResetPassword(@RequestBody String encryptedReq) {
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        Assert.isEmpty(userAccount.getNew_password(), "新密码不能为空");
        Assert.isEmpty(userAccount.getMobile(), "手机号不能为空");
        Assert.isEmpty(userAccount.getMobile_code(), "验证码不能为空");
        userService.resetPassword(userAccount);
        return rspSuccess();
    }

    /**
     * 绑定微信
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiBindWeiXin", produces = {"application/json;charset=UTF-8"})
    public String apiBindWeiXin(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getWeixin_tempcode(), "微信登陆临时编码不能为空");
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");

        //先获取此用户的微信UnionId
        WeiXinUserInfo weiXinUserInfo = userService.getWeiXinUserInfo(userAccount.getWeixin_tempcode());
        Assert.isEmpty(weiXinUserInfo.getUnionid(), "微信的UnionId获取失败");
        //查询用户信息
        UserFilter userFilter = new UserFilter();
        userFilter.setWeixin_unionid(weiXinUserInfo.getUnionid());
        UserAccount userAccount_db = userService.getUser(userFilter);

        if (userAccount_db != null) {
            throw new AppException(MessageFormat.format("已经绑定手机号:{0} 的账户,请先解绑"
                    , userAccount_db.getMobile()));
        }
        //绑定到传来的账户上
        userService.bindWeiXin(userAccount);
        return rspSuccess();
    }

    /**
     * 绑定qq
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiBindQQ", produces = {"application/json;charset=UTF-8"})
    public String apiBindQQ(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getQq_openid(), "qq openid 不能为空");
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        //查询用户信息
        UserFilter userFilter = new UserFilter();
        userFilter.setQq_openid(userAccount.getQq_openid());
        UserAccount userAccount_db = userService.getUser(userFilter);

        if (userAccount_db != null) {
            throw new AppException(MessageFormat.format("已经绑定手机号:{0} 的账户,请先解绑"
                    , userAccount_db.getMobile()));
        }
        //绑定到传来的账户上
        userService.bindQQ(userAccount);
        return rspSuccess();
    }

    /**
     * 解绑WeiXin
     * 解绑逻辑:解绑即要回到原始账号登陆,默认密码修改过,才能解绑
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiUnBindWeiXin", produces = {"application/json;charset=UTF-8"})
    public String apiUnBindWeiXin(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        //查询用户信息
        UserFilter userFilter = new UserFilter();
        userFilter.setUserid(userAccount.getId());
        UserAccount userAccount_db = userService.getUser(userFilter);

        if (userAccount_db.getUser_password().contains("default")) {
            return rspError("请先修改密码再解绑");
        }
        //解绑微信
        userService.unbindWeiXin(userAccount);
        return rspSuccess();
    }

    /**
     * 解绑qq
     * 跟解绑微信完全一样,需要实现时参考apiUnBindWeiXin
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiUnBindQQ", produces = {"application/json;charset=UTF-8"})
    public String apiUnBindQQ(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserAccount userAccount = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserAccount>>() {
        }).getFirstEntity();
        //数据验证
        Assert.isEmpty(userAccount.getId(), "用户id不能为空");
        //查询用户信息
        UserFilter userFilter = new UserFilter();
        userFilter.setId(userAccount.getId());
        UserAccount userAccount_db = userService.getUser(userFilter);

        if (userAccount_db.getUser_password().contains("default")) {
            rspError("请先修改密码再解绑");
        }
        //解绑微信
        userService.unbindWeiXin(userAccount);
        return rspSuccess();
    }

    /**
     * 获取用户列表
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiGetUserList", produces = {"application/json;charset=UTF-8"})
    public String apiGetUserList(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserFilter userFilter = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserFilter>>() {
        }).getFirstEntity();
        //取不同类型的用户列表
        PageData<UserAccount> pageData = new PageData<>();
        if (userFilter.getUser_type() == null) {
            userFilter.setUser_type("ALL");
        }
        switch (userFilter.getUser_type()) {
            case UserDic.UserType.GENERAL_USER_WITHOUT_COACH:
                pageData = userService.getGeneralUserList(userFilter);
                break;
            case UserDic.UserType.COACH:
                pageData = userService.getCoachList(userFilter);
                break;
            case UserDic.UserType.ALL:
                pageData = userService.getAllUserList(userFilter);
                break;
            default:
        }
        return rspSuccess(pageData);
    }

    /**
     * 保存用户权限
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiSaveUserLimit", produces = {"application/json;charset=UTF-8"})
    public String apiSaveUserLimit(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserLimit userLimit = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserLimit>>() {
        }).getFirstEntity();
        Assert.isEmpty(userLimit.getUserid(), "用户的Id不能为空");
        userService.saveUserlimit(userLimit);
        return rspSuccess();
    }

    /**
     * 获取用户权限
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiGetUserLimit", produces = {"application/json;charset=UTF-8"})
    public String apiGetUserLimit(@RequestBody String encryptedReq) {
        //反序列化取得对象
        UserFilter userFilter = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserFilter>>() {
        }).getFirstEntity();
        Assert.isEmpty(userFilter.getUserid(), "用户的Id不能为空");
        UserLimit result = userService.getUserLimit(userFilter);
        return rspSuccess(result);
    }

    /**
     * 获取当前用户附近的地点
     *
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiGetUserNearbyArea", produces = {"application/json;charset=UTF-8"})
    public String apiGetUserNearbyArea(@RequestBody String encryptedReq) {
        UserFilter userFilter = getRequestObjectWithoutToken(encryptedReq, new TypeReference<Request<UserFilter>>() {
        }).getFirstEntity();
        Assert.isEmpty(userFilter.getMyLatitude(), "当前用户的纬度不能为空");
        Assert.isEmpty(userFilter.getMyLongitude(), "当前用户的经度不能为空");
        Assert.isEmpty(userFilter.getDistance(), "distance距离字段不能为空");
        return rspSuccess(userService.getUserNearbyAreaList(userFilter));

    }

    /**
     * 模拟车的行驶轨迹
     *  切换 setDistanceDouble 的值 生成的四个点, 取最小的, 多个点轨迹类似车辆行驶轨迹
     * @param encryptedReq
     * @return
     */
    @PostMapping(value = "v1/apiGetCarUserNearbyArea", produces = {"application/json;charset=UTF-8"})
    public String apiGetCarUserNearbyArea(@RequestBody String encryptedReq) {
        LocationFilter locationFilter = new LocationFilter();
        locationFilter.setMyLatitude(104.071305);
        locationFilter.setMyLongitude(30.5454);
        locationFilter.setDistanceDouble(0.02);
        String str = JsonUtil.toJson(userService.getCurrentLocationRectangleDouble(locationFilter));
        System.out.println(str);

        return str;
    }


}
